library(forestTIME)
#> ! forestTIME is an experimental package and currently a work-in-progress. It is
#> not an official product of the US Forest Service.
library(dplyr)
#>
#> Attaching package: 'dplyr'
#>
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#>
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, unionData Download
fia_download() downloads zip files of all CSVs and extracts the necessary ones. It will skip downloading if the files already exist.
fia_download(
states = "DE",
download_dir = "fia",
keep_zip = TRUE
)Data Preparation
I need to make sure I have all the columns for population estimation and all the columns for carbon estimation using the walker code (documented better in annual_carbon_estimation.qmd).
fia_load() is a wrapper around rFIA::readFIA() and reads in all the required tables as a list of data frames.
#> [1] "COND" "PLOT" "PLOTGEOM"
#> [4] "POP_ESTN_UNIT" "POP_EVAL_TYP" "POP_EVAL"
#> [7] "POP_PLOT_STRATUM_ASSGN" "POP_STRATUM" "TREE"
fia_tidy() gets all the columns needed into a single table and create the unique plot and tree IDS, plot_ID and tree_ID.
data <- fia_tidy(db)
#> ℹ Wrangling data
#> ✔ Wrangling data [326ms]
#>
dataCheck that each tree has only 1 entry per year
Annualize
Annualization of the panel data is performed by fia_annualize(). “Under the hood” this is running expand_data() followed by interpolate_data() and then adjust_mortality(). While you can run each of these steps separately, it is not generally recommended as there are “artifacts” introduced by some steps that are not “cleaned up” until later steps. One good reason to run this step-wise would be if you are wanting to produce a result both with and without using MORTYR since the slowest step is interpolate_data().
data_midpt <- fia_annualize(data, use_mortyr = FALSE)
#> ℹ Adjusting for mortality
#> ℹ Interpolating between surveys
#> ℹ Expanding years between surveys
#> ✔ Expanding years between surveys [3.5s]
#>
#> ℹ Interpolating between surveys
✔ Interpolating between surveys [17.8s]
#>
#> ℹ Adjusting for mortality
✔ Adjusting for mortality [26.3s]data_midpt_stepwise <- data |>
expand_data() |> #has placeholder values (e.g. 999) for some variables to ensure correct interpolation
interpolate_data() |> #has incorrect values for trees that die or fall between surveys
adjust_mortality(use_mortyr = FALSE)
#> ℹ Adjusting for mortality
#> ℹ Interpolating between surveys
#> ℹ Expanding years between surveys
#> ✔ Expanding years between surveys [3.2s]
#>
#> ℹ Interpolating between surveys
✔ Interpolating between surveys [17.3s]
#>
#> ℹ Adjusting for mortality
✔ Adjusting for mortality [26s]
identical(data_midpt, data_midpt_stepwise)
#> [1] TRUELet’s break down what happens in each step.
expand_data() expands the table to include all years between inventories. Time-invariant columns including plot_ID, SPCD, ECOSUBCD, DESIGNCD, CONDID, INTENSITY and PROP_BASIS are simply filled down. Some NAs thar represent missing values in inventory years are replaced with placeholder values (e.g. 999, 0 for CULL) to distinguish them from the NAs between surveys to aid in linear interpolation in later steps.
data_expanded <- expand_data(data)
#> ℹ Expanding years between surveys
#> ✔ Expanding years between surveys [3.2s]
#>
data_expandedinterpolate_data() then interpolates continuous and categorical variables between surveys. Continuous variables are interpolated with inter_extra_polate() and categorical variables are interpolated with step_interp(). interpolate_data() also joins in the TPA_UNADJ column based on DESIGNCD and DIA. If trees are interpolated to below FIA thresholds for being measured (DIA < 1, ACTUALHT < 1 for woodland species and < 4.5 for non-woodland species), they are assumed to be fallen dead and have STATUSCD set to 2 and STANDING_DEAD_CD set to 0.
data_interpolated <- interpolate_data(data_expanded)
#> ℹ Interpolating between surveys
#> ✔ Interpolating between surveys [14s]
#>
data_interpolatedadjust_mortality() adjusts all columns related to mortality (STATUSCD, STANDING_DEAD_CD, DECAYCD, and measurements like DIA, HT, ACTUALHT, CULL, CR etc.). E.g. DECAYCD only applies to standing dead trees and STANDING_DEAD_CD only applies to trees with STATUSCD 2 (dead).
data_mortyr <- adjust_mortality(data_interpolated, use_mortyr = TRUE)
#> ℹ Adjusting for mortality
#> Warning: ! No recorded `MORTYR` in data.
#> ℹ Setting `use_mortyr` to `FALSE`
#> ✔ Adjusting for mortality [8.6s]
#>
data_midpt <- adjust_mortality(data_interpolated, use_mortyr = FALSE)
#> ℹ Adjusting for mortality
#> ✔ Adjusting for mortality [8.5s]
#>
all.equal(data_mortyr, data_midpt)
#> [1] TRUEThese tables will be identical in states like RI where MORTYR is never used, but in states that have records for MORTYR these tables would differ slightly for some subset of trees.
Carbon Estimation
fia_estimate() uses code provided by David Walker to calculate carbon and biomass variables using the National Scale Volume and Biomass estimators (NSVB) (Westfall et al. 2024).
data_midpt_carbon <- fia_estimate(data_midpt)
#> ℹ Prepping for estimating carbon
#> ✔ Prepping for estimating carbon [248ms]
#>
#> ⠙ Estimating carbon: prepping data
#> ⠹ Estimating carbon: predicting merchantable stem wood volume
#> ⠸ Estimating carbon: predicting sawlog stem wood volume
#> ⠼ Estimating carbon: predicting total stem bark weight
#> ✔ Estimating carbon: harmonizing components [15.6s]
#>
data_midpt_carbon